home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
130_01
/
vfile.c
< prev
next >
Wrap
Text File
|
1985-03-09
|
9KB
|
266 lines
/***********************************************************\
* *
* VFILE consists of 5 functions which simulate a "BASIC *
* RANDOM FILE" structure using fixed length records of *
* varying pre-specified size. A record may be up to 255 *
* chars long. It is the programmer's responsibility to *
* keep track of the contents of his record, and VFILE's *
* responsibility to write and read the record to and from *
* the correct position in file. Record numbers are *
* maximum 32767. VFILE will give ERROR if reading past *
* end of file or exceeding legal bounds. It will pad *
* as-yet-unwritten internal records with nulls. An error *
* is returned if there is not enough disk space for *
* either the record or the padding. There is a sixth *
* function (vset), which is used internally. *
* *
* The structure "_vbuf" must be included in the *
* programme, and each file must reserve a VBUFSIZ area *
* for buffering. This area will vary depending on NSECTS *
* in BDSCIO.H THE VALUE OF NSECTS MUST BE GREATER *
* THAN TWO. The definitions of _vbuf and VBUFSIZ *
* should eventually find their way into BDSCIO.H *
* I have included them in this source for clarity. *
* *
\************************************************************
Version 1.0 by Greg Lister
19th November, 1980 */
#include "bdscio.h"
#define VBUFSIZ NSECTS * SECSIZ + 14
struct _vbuf
{ int fd; /* File Descriptor */
int eof; /* Actual EOF of file */
int pos; /* Current record's position in buffer */
int len; /* Record length */
int sta; /* Start sector of buffer */
int cnt; /* Number of sectors in buffer */
int wflag; /* flag set if buffer written to */
char buffer[NSECTS * SECSIZ];
};
vset(recno,vbuf)
int recno;
struct _vbuf *vbuf;
/************************************************\
* *
* Sets up buffer for random reads and writes. *
* Flushes buffer if necessary and fills buffer *
* with required data. Sets pointer to beginning*
* of r/w record. Fills unwritten buffer with *
* nulls. Returns ERROR if cannot flush or *
* if hard read error. Returns NULL if *
* required buffer is not yet written. Returns *
* -2 if required sector (128 byte) is not yet *
* written. Else returns valid sectors in buf. *
* *
\************************************************/
{
int tmp,blkno,bss,blkoff,secno,bufsec,endrec;
blkno=recno>>7; /* Block Number */
bss=blkno*vbuf->len; /* Block start Sector */
blkoff=(recno%128)*vbuf->len; /* Offset into Block */
secno=bss+(blkoff>>7); /* Sector # of start of rec */
endrec=bss+((blkoff+vbuf->len-1)>>7);/* Sec# END of rec */
bufsec=(secno/(NSECTS-2))*(NSECTS-2); /* Start sec of buf */
vbuf->pos=vbuf->buffer+((secno-bufsec)<<7)+(blkoff%128);
if(bufsec!=vbuf->sta)
{ if(vbuf->wflag)
{ seek(vbuf->fd,vbuf->sta,0);
if(write(vbuf->fd,vbuf->buffer,vbuf->cnt)<vbuf->cnt)
return ERROR;
if((tmp=tell(vbuf->fd))>vbuf->eof)
vbuf->eof=tmp;
vbuf->wflag=0;
}
if((vbuf->sta=bufsec)>vbuf->eof) return NULL;
seek(vbuf->fd,bufsec,0);
if((vbuf->cnt=read(vbuf->fd,vbuf->buffer,NSECTS))<0)
return ERROR;
if(vbuf->cnt!=NSECTS)
fillb(vbuf->buffer+(vbuf->cnt<<7),
vbuf->buffer+(NSECTS<<7),0,0);
}
if(endrec-bufsec>=vbuf->cnt) return -2;
return vbuf->cnt;
}
vwrite(recno,vbuf,str)
int recno;
struct _vbuf *vbuf;
char *str;
/********************************************************\
* *
* Writes data at str to file vbuf at recno. Pads file *
* with NULLS if skipping unwritten sections of file. *
* Returns ERROR if full disk, unopened file etc *
* Returns ERROR if bad record #; else returns OK *
* *
\********************************************************/
{ int tmp,tmp1,tmp2;
if(recno<0) return ERROR;
if((tmp=vset(recno,vbuf))==-1) return ERROR;
if(tmp==0)
{ fillb(vbuf->buffer,NSECTS<<7,0,1);
seek(vbuf->fd,vbuf->eof,0);
while((vbuf->eof=tell(vbuf->fd))<vbuf->sta)
if(write(vbuf->fd,vbuf->buffer,1)>1) return ERROR;
}
movmem(str,vbuf->pos,vbuf->len);
tmp2=vbuf->buffer;
tmp1=(127+vbuf->pos-tmp2+vbuf->len)>>7;
if(tmp1>vbuf->cnt)
vbuf->cnt=tmp1;
vbuf->wflag=1;
return OK;
}
vread(recno,vbuf,str)
int recno;
struct _vbuf *vbuf;
char str[];
/************************************************\
* *
* Reads record 'recno' from file to 'str'. *
* Returns ERROR if hard error (unopened *
* file etc) or if attempt is made to read *
* past current end of file. Returns no of *
* secs read in. ERROR if bad recno. *
* *
\************************************************/
{ int tmp;
if(recno<0) return ERROR;
tmp=vbuf->sta;
if(vset(recno,vbuf)<1)
{
vbuf->sta=tmp;
return ERROR;
}
movmem(vbuf->pos,str,vbuf->len);
return vbuf->cnt;
}
vclose(vbuf)
struct _vbuf *vbuf;
/************************************************\
* *
* Closes file using vbuf. Returns OK if *
* closed successfully. ERROR if error. *
* *
\************************************************/
{ if(vbuf->wflag)
{ seek(vbuf->fd,vbuf->sta,0);
if(write(vbuf->fd,vbuf->buffer,vbuf->cnt)<0)
return ERROR;
}
return close(vbuf->fd);
}
vopen(filename,vbuf,reclen)
int reclen;
char filename[];
struct _vbuf *vbuf;
/************************************************\
* *
* Opens filename for v-format buffered io *
* Reclen is the specified record length *
* (may be up to 255 chars). Vbuf is a *
* VBUFSIZ buffer ((128 * NSECTS)+14) *
* **NOTE** NSECTS must be 3 or more for this *
* file structure to work. *
* Returns ERROR if reclen is out of range *
* or if open error occurs (ie file doesn't *
* exist - use vcreat) *
* *
\************************************************/
{ if((vbuf->len=reclen)>255)return ERROR;
if(reclen<0) return ERROR;
if((vbuf->fd=open(filename,2))<0) return ERROR;
vbuf->sta=vbuf->cnt=-1;
vbuf->wflag=0;
vbuf->pos=vbuf->buffer;
vbuf->eof=telend(filename);
return vbuf->fd;
}
vcreat(filename,vbuf,reclen)
int reclen;
char filename[];
struct _vbuf *vbuf;
/************************************************\
* *
* Creates a file as vopen (see above) *
* *
\************************************************/
{ fabort(creat(filename));
return vopen(filename,vbuf,reclen);
}
/****************************************************\
* *
* The next function is general and not only a part *
* of the VFILE package. It will tell you where the *
* end of your file is to be found. *
* *
\*